import random

from django.http import HttpResponse
from django.shortcuts import render

# Create your views here.
from rest_framework import status
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from rest_framework.views import APIView

from celery_tasks import main
from celery_tasks.main import send_sms_code
from image_codes.serializers import image_code_serializer
from meiduo import constants
from meiduo.libs.captcha.captcha import captcha
from django_redis import get_redis_connection
from meiduo.utils.yuntongxun import sms
import logging

# 生成日志器对象
logger = logging.getLogger('django')


class get_image_codes(APIView):
    """生成图片验证码
    1.接收参数  ?p<image_code_id> 在url路径参数传参的时候,会自动进行正则匹配
                所以收到的参数是合规的,不再需要进行校验,用不到序列化器的校验功能
    2.生成图片验证码   使用第三方工具captcha
    3.将图片验证码的真实值保存到redis数据库
    4.返回图片验证码  drf的resp不能进行bytes类型的转换 所以要用django原生的httpresp
    """

    def get(self, request, image_code_id):
        # 生成图片验证码
        text, image = captcha.generate_captcha()
        # 将图片验证码保存到redis 以dev配置中的reids库作为参数生成redis连接对象
        redis_conn = get_redis_connection('verify_code')
        # 保存到数据库并设置有效期
        redis_conn.setex('img_code_%s' % image_code_id, constants.IMAGE_CODE_EXPIRES, text)
        # 将图片验证码返回给前端页面
        return HttpResponse(image, content_type='image/jpg')


class get_sms_code(GenericAPIView):
    """获取短信验证码
    1.接收前端传过来的数据  路径参数mobile  查询字符串 text image_code_id
    2.校验参数  可以使用序列化器
    3.生成短信验证码
    4.保存短信验证码到redis
    5.返回发送成功或失败的响应
    """
    serializer_class = image_code_serializer

    def get(self, request, mobile):
        # 将查询字符串中的参数传入序列化器进行校验,反序列化校验的时候要写上data=..
        sl = self.get_serializer(data=request.query_params)
        # 校验工作在序列化器中完成
        sl.is_valid(raise_exception=True)

        # 生成短信验证码
        sms_code = "%06d" % random.randint(0, 999999)
        print("短信验证码>>>%s" % sms_code)

        # 保存短信验证码与发送记录到数据库
        redis_conn = get_redis_connection('verify_code')
        # redis管道可以一次行提交多个操作到redis  节省了网络通信时间
        pl = redis_conn.pipeline()
        pl.setex("sms_%s" % mobile, constants.SMS_CODE_EXPIRES, sms_code)
        # 设置短信验证码重新发送时限
        pl.setex("send_flag_%s" % mobile, constants.SEND_SMS_CODE_INTERVAL, 1)
        pl.execute()

        # 发送短信验证码
        expires_time = constants.SMS_CODE_EXPIRES // 60
        main.send_sms_code.delay(mobile, sms_code, expires_time)

        return Response({"message": "ok"})
